use anyhow::Result;
use std::net::SocketAddr;
use std::time::Duration;
use tokio::sync::oneshot;
use tokio::time::sleep;
use tracing::info;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::{EnvFilter, fmt};

use p2p_project::app::Server;
use p2p_project::pb::{PublishFileRequest, PublishFileResponse, dfs_client::DfsClient};

struct TestServer {
    pub addr: SocketAddr,
    sender: Option<oneshot::Sender<()>>,
}

impl Drop for TestServer {
    fn drop(&mut self) {
        info!("Dropping TestServer");
        if let Some(tx) = self.sender.take() {
            let _ = tx.send(());
        }
    }
}

// 启动 gRPC 服务的辅助函数
async fn start_test_server() -> Result<TestServer> {
    // 初始化日志
    tracing_subscriber::registry()
        .with(fmt::layer())
        .with(EnvFilter::from_default_env())
        .init();

    // 动态获取可用端口
    let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
    let port = listener.local_addr()?.port();
    drop(listener); // 释放临时监听，让服务使用该端口

    // 创建关闭信号通道（关键改进）
    let (shutdown_tx, shutdown_rx) = oneshot::channel();

    // 启动服务
    let server_addr = format!("127.0.0.1:{}", port);
    let temp_dir = tempfile::tempdir_in("./")?;
    let base_path = temp_dir.path().to_path_buf();
    info!("base_path: {:?}", base_path);
    tokio::spawn(async move {
        let mut server = Server::new(port, base_path);
        // 启动服务并等待关闭信号
        if let Err(e) = server.start().await {
            eprintln!("Server start failed: {}", e);
        }
        // 等待关闭信号（关键改进）
        let _ = shutdown_rx.await;
        if let Err(e) = server.stop().await {
            eprintln!("Server stop failed: {}", e);
        }

        if let Err(e) = temp_dir.close() {
            eprintln!("Failed to close temp dir: {}", e);
        }
    });

    // 健康检查：等待端口就绪（关键改进）
    wait_for_port_ready(port).await;

    Ok(TestServer {
        addr: server_addr.parse()?,
        sender: Some(shutdown_tx),
    })
}

// 新增：端口健康检查函数
async fn wait_for_port_ready(port: u16) {
    let addr = format!("127.0.0.1:{}", port);
    let mut attempts = 0;
    loop {
        match tokio::net::TcpStream::connect(&addr).await {
            Ok(_) => break,
            Err(_) if attempts < 20 => {
                // 最多等待4秒（20次*200ms）
                sleep(Duration::from_millis(200)).await;
                attempts += 1;
            }
            Err(e) => panic!("Port {} not ready: {}", port, e),
        }
    }
}

#[tokio::test]
async fn test_grpc_service() -> Result<()> {
    // 获取动态端口和关闭信号（关键改进）
    let server = start_test_server().await?;

    // 客户端连接逻辑（保持原有，但可移除重试，因健康检查已确保端口就绪）
    let mut client = DfsClient::connect(format!("http://{}", server.addr)).await?;

    // 构建请求（保持原有）
    let request = tonic::Request::new(PublishFileRequest {
        file_path: "fixtures/word2.txt".to_string(),
        public: false,
    });

    // 调用gRPC方法（保持原有）
    let response = client.publish_file(request).await?;
    let response: PublishFileResponse = response.into_inner();
    assert!(response.success);
    assert!(response.error.is_empty());

    Ok(())
}
